/*
 ============================================================================
 Name		: ARCheckersMobAppView.cpp
 Author	  : 
 Copyright   : Your copyright notice
 Description : Application view implementation
 ============================================================================
 */

// INCLUDE FILES
#include <coemain.h>
#include "ARCheckersMobAppView.h"

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CARCheckersMobAppView* CARCheckersMobAppView::NewL(const TRect& aRect)
	{
	CARCheckersMobAppView* self = CARCheckersMobAppView::NewLC(aRect);
	CleanupStack::Pop(self);
	return self;
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CARCheckersMobAppView* CARCheckersMobAppView::NewLC(const TRect& aRect)
	{
	CARCheckersMobAppView* self = new (ELeave) CARCheckersMobAppView;
	CleanupStack::PushL(self);
	self->ConstructL(aRect);
	return self;
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CARCheckersMobAppView::ConstructL(const TRect& aRect)
	{
	// Create a window for this application view
	CreateWindowL();

	// Set the windows size
	SetRect(aRect);

	// Activate the window, which makes it ready to be drawn
	ActivateL();
	
	iFrame = 0;                              // Initialize frame counter
		    
		EGLConfig Config;                        // Describes the format, type and 
					
		// Get the display for drawing graphics
		iEglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
		if ( iEglDisplay == NULL )
			{
			_LIT(KGetDisplayFailed, "eglGetDisplay failed");
			User::Panic( KGetDisplayFailed, 0 );
			}

		// Initialize display 
		if ( eglInitialize( iEglDisplay, NULL, NULL ) == EGL_FALSE )
			{
			_LIT(KInitializeFailed, "eglInitialize failed");
			User::Panic( KInitializeFailed, 0 );
			}

		EGLConfig *configList = NULL;            // Pointer for EGLConfigs
		EGLint numOfConfigs = 0; 
		EGLint configSize   = 0;

		// Get the number of possible EGLConfigs 
		if ( eglGetConfigs( iEglDisplay, configList, configSize, &numOfConfigs ) 
			== EGL_FALSE )
			{
			_LIT(KGetConfigsFailed, "eglGetConfigs failed");
			User::Panic( KGetConfigsFailed, 0 );
			}

		configSize = numOfConfigs;

		// Allocate memory for the configList 
		configList = (EGLConfig*) User::Alloc( sizeof(EGLConfig)*configSize );
		if ( configList == NULL )
			{
			_LIT(KConfigAllocFailed, "config alloc failed");
			User::Panic( KConfigAllocFailed, 0 );
			}

		/* Define properties for the wanted EGLSurface.
		   To get the best possible performance, choose
		   an EGLConfig with a buffersize matching
		   the current window's display mode*/
		TDisplayMode DMode = Window().DisplayMode();
		TInt BufferSize = 0;

		switch ( DMode )
			 {
			 case(EColor4K):
				 BufferSize = 12;
				 break;
			 case(EColor64K):
				 BufferSize = 16;
				 break;
			 case(EColor16M):
				 BufferSize = 24;
				 break;
			 case(EColor16MU):
				 BufferSize = 32;
				 break;
			 default:
				 _LIT(KDModeError,       "unsupported displaymode");
				 User::Panic( KDModeError, 0 );
				 break;
			 }

		// Define properties for the wanted EGLSurface 
		const EGLint attrib_list[] = { EGL_BUFFER_SIZE,BufferSize,   
									   EGL_NONE };

		// Choose an EGLConfig that best matches to the properties in attrib_list 
		if ( eglChooseConfig( iEglDisplay, attrib_list, configList, configSize, 
							 &numOfConfigs ) == EGL_FALSE )
			{
			_LIT(KChooseConfigFailed, "eglChooseConfig failed");
			User::Panic( KChooseConfigFailed, 0 );
			}

		Config = configList[0];   // Choose the best EGLConfig. EGLConfigs 
								  // returned by eglChooseConfig are sorted so 
								  // that the best matching EGLConfig is first in
								  // the list.
		User::Free( configList ); // Free configList, not used anymore.

		// Create a window where the graphics are blitted 
		iEglSurface = eglCreateWindowSurface( iEglDisplay, Config, &Window(), NULL );
		if ( iEglSurface == NULL )
			{
			_LIT(KCreateWindowSurfaceFailed, "eglCreateWindowSurface failed");
			User::Panic( KCreateWindowSurfaceFailed, 0 );
			}

		// Create a rendering context 
		iEglContext = eglCreateContext( iEglDisplay, Config, NULL, NULL );
		if ( iEglContext == NULL )
			{
			_LIT(KCreateContextFailed, "eglCreateContext failed");
			User::Panic( KCreateContextFailed, 0 );
			}

		/* Make the context current. Binds context to the current rendering thread
		   and surface.*/
		if ( eglMakeCurrent( iEglDisplay, iEglSurface, iEglSurface, iEglContext ) 
			== EGL_FALSE )
			{
			_LIT(KMakeCurrentFailed, "eglMakeCurrent failed");
			User::Panic( KMakeCurrentFailed, 0 );
			}
		
			TSize size;
		    size = this->Size();

		    iARCheckersMob = CARCheckersMob::NewL( size.iWidth, size.iHeight ); // Create an instance of SimpleCube
		    
		    iARCheckersMob->AppInit();
			iPeriodic = CPeriodic::NewL( CActive::EPriorityIdle );
			
			iPeriodic->Start( 100, 100, 
			                      TCallBack( CARCheckersMobAppView::DrawCallBack, this ) );
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::CARCheckersMobAppView()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CARCheckersMobAppView::CARCheckersMobAppView()
	{
	// No implementation required
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::~CARCheckersMobAppView()
// Destructor.
// -----------------------------------------------------------------------------
//
CARCheckersMobAppView::~CARCheckersMobAppView()
	{
	delete iPeriodic;

		    if ( iARCheckersMob )
		        {
		        iARCheckersMob->AppExit();
		        delete iARCheckersMob;
		        }

		    eglMakeCurrent( iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
		    eglDestroySurface( iEglDisplay, iEglSurface ); 
		    eglDestroyContext( iEglDisplay, iEglContext );
		    eglTerminate( iEglDisplay );
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::Draw()
// Draws the display.
// -----------------------------------------------------------------------------
//
void CARCheckersMobAppView::Draw(const TRect& /*aRect*/) const
	{
	// Get the standard graphics context
	CWindowGc& gc = SystemGc();

	// Gets the control's extent
	TRect drawRect(Rect());

	// Clears the screen
	gc.Clear(drawRect);

	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::SizeChanged()
// Called by framework when the view size is changed.
// -----------------------------------------------------------------------------
//
void CARCheckersMobAppView::SizeChanged()
	{
	DrawNow();
	}

// -----------------------------------------------------------------------------
// CARCheckersMobAppView::HandlePointerEventL()
// Called by framework to handle pointer touch events.
// Note: although this method is compatible with earlier SDKs, 
// it will not be called in SDKs without Touch support.
// -----------------------------------------------------------------------------
//
void CARCheckersMobAppView::HandlePointerEventL(
		const TPointerEvent& aPointerEvent)
	{

	// Call base class HandlePointerEventL()
	CCoeControl::HandlePointerEventL(aPointerEvent);
	}

TInt CARCheckersMobAppView::DrawCallBack( TAny* aInstance )
    {
    CARCheckersMobAppView* instance = (CARCheckersMobAppView*) aInstance;
    instance->iFrame++;
    
    // Call the main OpenGL ES Symbian rendering 'loop' 
    instance->iARCheckersMob->AppCycle( instance->iFrame );
    
    // Call eglSwapBuffers, which blit the graphics to the window 
    eglSwapBuffers( instance->iEglDisplay, instance->iEglSurface );
    
    // To keep the background light on 
    if ( !(instance->iFrame%100) )
        {
        User::ResetInactivityTime();
        }
    
    /* Suspend the current thread for a short while. Give some time 
       to other threads and AOs, avoids the ViewSrv error in ARMI and
       THUMB release builds. One may try to decrease the callback 
       function instead of this. */ 
    if ( !(instance->iFrame%50) )
        {
        User::After(0);
        }
    
    return 0; 
    }

// End of File
